<template>
  <div class="wrapper" @contextmenu.prevent="menuVisible=false" @click="menuVisible=false">
    <div class="main" ref="main" @mousedown.stop="handlerClickBox">
      <!-- 普通 -->
      <Element @click="handleSelectElement" @mousedown=""  v-for="item in excludeGroupAndExcludeSelectedElements" :key="item.id" :element="item"></Element>

      <!-- 组合 -->
      <!-- <div v-for="group in groups" class="group-elements-wrapper" :style="getGroupTransformStyleObj(group)">
        <Element :wrapper-transform="group" @click="handleSelectElement" v-if="item.group===group.id"  v-for="item in excludeSelectedAndGroupElements" :key="item.id" :element="item"></Element>
      </div> -->

      <!-- 多选中 -->
      <div class="selected-elements-wrapper" :style="SelecteTransformStyleObj" v-show="selectedElementIds.length>1">
        <Transform   v-model="newSelectedElementsTransform" @changeEnd="handlerSelectedElementsTransformChange" @resize="handlerSelectedElementsTransformChange">
            <Element :wrapper-transform="selectedElementsTransform"  v-for="item in selectedElements" :key="item.id" :element="item" ></Element>
            <!-- <div v-for="group in groups" class="group-elements-transform" >
              <Element :wrapper-transform="selectedElementsTransform" @click="handleSelectElement" v-if="item.group===group.id"  v-for="item in selectedElements" :key="item.id" :element="item"></Element>
            </div> -->
        </Transform>
      </div>
      <div class="box" :style="BoxStyleObj"></div>
    </div>
    <div class="attr" v-if="!!curElementId" :style="selectedElementsTransform" @click.stop="menuVisible=false">
      <div class="handler" @mousedown.stop="handleClickEditorWrapper">
        <Icon type="navicon-round"></Icon>
      </div>
      <Paramster></Paramster>
    </div>
    <right-menu v-show="menuVisible" :pos="pos" @click="menuVisible=false"></right-menu>
  </div>
</template>

<script>
import { Vue, Component, Watch } from 'vue-property-decorator'
import $ from "jquery"
import {throttle} from "lodash"
import Transform from "./Transform.vue"
import Element from "./Element.vue"
import Paramster from "./Paramster.vue"
import RightMenu from "./RightMenu.vue"
import {
  State,
  Getter,
  Action
} from 'vuex-class'
@Component({
  components: {
    Transform,
    Element,
    Paramster,
    RightMenu
  }
})
export default class Editor extends Vue {
  @Getter curElement
  @State selectedElementsTransform
  @Getter selectedElements
  @Getter excludeSelectedElements
  @Getter excludeSelectedAndGroupElements
  @Getter excludeGroupAndSelectedElements
  @Getter excludeGroupAndExcludeSelectedElements
  @State curElementId
  @State groups
  @State elementList
  @State selectedElementIds
  // @State menuVisible
  @Action actSelectCurElement
  @Action actAddSelectedElements
  @Action actCancelSelectedElements
  @Action actChangeSelectedElementsTansform
  @Action actRemoveElement
  @Action actAddElement
  // @Action setMenuVisible
  transform = {
    right: 0,
    top: 60
  }
  old = {
    right: 0,
    top: 60
  }
  gap = {
    x: 0,
    y: 0
  }
  pos = {
    x: 0,
    y: 0
  }
  box = {
    left: 0,
    top: 0,
    width: 0,
    height: 0,
    display: 'none'
  }
  ctrlKey=false;
  menuVisible = false;

  newSelectedElementsTransform={
    width: 0,
    height: 0,
    left: 0,
    top: 0
  }
  newSelectedElementsIds=[]
  get StyleObj () {
    return {
      right: this.transform.right + "px",
      top: this.transform.top + "px",
      width: this.curElement.type === 'chart' ? "500px" : "400px"
    }
  }

  get BoxStyleObj () {
    return {
      left: this.box.left + "px",
      top: this.box.top + "px",
      width: this.box.width + "px",
      height: this.box.height + "px",
      display: this.box.display
    }
  }
  get SelecteTransformStyleObj () {
    return {
      width: this.newSelectedElementsTransform.width + "px",
      height: this.newSelectedElementsTransform.height + "px",
      left: this.newSelectedElementsTransform.left + "px",
      top: this.newSelectedElementsTransform.top + "px"
    }
  }

  @Watch('selectedElementsTransform')
  onSelectElementsChanged () {
    this.newSelectedElementsTransform = {...this.selectedElementsTransform}
  }

  getGroupTransformStyleObj (transform) {
    return {
      width: transform.width + "px",
      height: transform.height + "px",
      left: transform.left + "px",
      top: transform.top + "px"
    }
  }

  _handlerSelectedElementsTransformChange () {
    this.actChangeSelectedElementsTansform(this.newSelectedElementsTransform)
  }
  handlerSelectedElementsTransformChange :any=function () {}

  handlerDocumentClick (): void {
    // console.log(1);
  }

  handleClickEditorWrapper (e):void {
    this.gap.x = e.clientX
    this.gap.y = e.clientY
    this.old.top = this.transform.top
    this.old.right = this.transform.right
    $(document).on("mousemove", this.handlerMousemoveEditorWrapper)
    $(document).on("mouseup", this.unHandlerMousemove)
  }
  handlerMousemoveEditorWrapper (e): void {
    let right = this.old.right + this.gap.x - e.clientX
    let top = this.old.top + e.clientY - this.gap.y
    this.transform.right = right
    this.transform.top = top
  }
  unHandlerMousemove (e): void {
    let right = this.transform.right
    let top = this.transform.top
    let maxRight = document.body.clientWidth - 500
    this.transform.right = right <= 50 ? 0 : (right >= (maxRight - 50) ? maxRight : right)
    this.transform.top = top <= 110 ? 60 : top
    $(document).off("mousemove", this.handlerMousemoveEditorWrapper)
  }
  handlerClickBox (e): void {
    this.gap.x = e.clientX
    this.gap.y = e.clientY
    this.box.display = "block"
    this.newSelectedElementsIds=[];
    $(document).on("mousemove", this.handlerMousemoveBox)
    $(document).on("mouseup", this.unHandlerMousemoveBox)
  }
  handlerMousemoveBox (e): void {
    this.box.width = Math.abs(e.clientX - this.gap.x)
    this.box.height = Math.abs(e.clientY - this.gap.y)
    this.box.left = Math.min(e.clientX, this.gap.x) - $(this.$refs.main).offset().left
    this.box.top = Math.min(e.clientY, this.gap.y) - $(this.$refs.main).offset().top
    this.elementList.forEach(el => {
      const { width, height, top, left } = el.transform;
      if ((e.clientX >= (left + $(this.$refs.main).offset().left) && e.clientX <= (width + left +$(this.$refs.main).offset().left)) && (e.clientY >= (top+$(this.$refs.main).offset().top) && e.clientY <= (height + top+$(this.$refs.main).offset().top))) {
        if (this.newSelectedElementsIds.indexOf(el.id) === -1) {
          this.newSelectedElementsIds.push(el.id);
        }       
      }
    })
  }
  unHandlerMousemoveBox (e): void {
    this.box.display = "none"
    if (this.newSelectedElementsIds.length > 0) {
      this.actSelectCurElement(null)
      this.actAddSelectedElements([...this.newSelectedElementsIds])
    }
    
    $(document).off("mousemove", this.handlerMousemoveBox)
  }
  handleSelectElement (element) {
    if (this.curElementId === element.id) {
      return
    }

    if (element.type === "group") {
      let groupIds = [element.id, ...element.extra]
      if (this.ctrlKey) {
        groupIds.push(this.curElementId)
        this.actSelectCurElement(this.selectedElementIds > 0 ? null : element.id)
        this.actAddSelectedElements(groupIds)
      } else {
        this.actSelectCurElement(element.id)
        this.actCancelSelectedElements()
        this.actAddSelectedElements(groupIds)
      }
    } else {
      if (this.ctrlKey) {
        this.actAddSelectedElements([element.id, this.curElementId])
        this.actSelectCurElement(null)
      } else {
        this.actCancelSelectedElements();
        this.actSelectCurElement(element.id)
      }
    }
    
    this.menuVisible = false
  }

  handlerElementRightClick (e, element) {
    // this.setMenuVisible(true);
    this.actSelectCurElement(element.id)
    this.menuVisible = true
    this.pos.x = e.clientX
    this.pos.y = e.clientY
  }
  mounted () {
    this.handlerSelectedElementsTransformChange = throttle(this._handlerSelectedElementsTransformChange, 10, {leading: false})
    this.onSelectElementsChanged()
    $(document).on("keydown", (e) => {
      if (e.keyCode === 91 || e.keyCode === 17) {
        this.ctrlKey = true
      }
    })
    $(document).on("keyup", (e) => {
      this.ctrlKey = false
    })

  }
}
</script>
<style lang="less" scoped>
.selected-elements-wrapper,.group-elements-wrapper{
  position: absolute;
}
.wrapper{
  position: relative;
}
.main{
  position: relative;
  min-height: 600px;
  border:1px dotted #ddd;
}
.attr{
  width:500px;
  position: fixed;
  right: 0;
  top: 60px;
  bottom:0;
  border: 1px solid #ddd;
  background: #373941;
  color: #fff;
  height:calc(100vh - 60px);
  padding-top: 20px;
}
.handler{
  height: 20px;
  line-height: 20px;
  text-align: center;
  font-size: 16px;
  position: absolute;
  left:0;
  top:0;
  width:100%;
  // cursor: crosshair;
  cursor: move;
}
.box {
  position: absolute;
  border: 1px solid #ccc;
}
</style>
